#include <Indicators\Indicators.mqh>

// 输入参数，用于指定CCI指标的周期
input int CCI_Period = 14;
// 定义黄金的交易品种代码
#define SYMBOL "GOLD"
// 定义获取CCI数值的K线数量
#define KLINE_NUMBER 30000
// 定义是否使用固定周期，1 表示使用固定周期，0 表示使用当前图表周期
#define USE_FIXED_PERIOD 0
// 固定的K线时间周期为15分钟
#define FIXED_TIMEFRAME_PERIOD PERIOD_M15
// 全局变量，用于存储CCI句柄
int hCCI;

// 动态数组声明
double cciValues[];
datetime klineTimes[];
double lowPrices[];
double highPrices[];
double reversedCciValues[];
datetime reversedKlineTimes[];
double reversedLowPrices[];
double reversedHighPrices[];
double qualifiedCciValues[];


// 将时间转换为中国时间
datetime ConvertToChinaTime(datetime originalTime) {
    return originalTime + 8 * 3600; // 东八区（UTC+8），8小时的秒数
}
// 比较三个元素的函数（修正数组参数传递方式）
void CompareThreeElements(double &qualifiedCciValues[], int qualifiedCount, 
    double &reversedLowPrices[], double &reversedHighPrices[],
    datetime &reversedKlineTimes[], double &reversedCciValues[]) 
{
    for (int i = 0; i < qualifiedCount - 2; i++) 
    {
        int index0 = -1, index1 = -1, index2 = -1;
        // 找出qualifiedCciValues[i]在reversedCciValues中的索引
        for (int j = 0; j <= KLINE_NUMBER; j++) 
        {
            if (qualifiedCciValues[i] == reversedCciValues[j]) 
            {
                index0 = j;
                break;
            }
        }

        // 找出qualifiedCciValues[i + 1]在reversedCciValues中的索引
        for (int j = 0; j <= KLINE_NUMBER; j++) 
        {
            if (qualifiedCciValues[i + 1] == reversedCciValues[j]) 
            {
                index1 = j;
                break;
            }
        }
        // 找出qualifiedCciValues[i + 2]在reversedCciValues中的索引
        for (int j = 0; j <= KLINE_NUMBER; j++) 
        {
            if (qualifiedCciValues[i + 2] == reversedCciValues[j]) 
            {
                index2 = j;
                break;
            }
        }

        if (index0 != -1 && index1 != -1 && index2 != -1) 
        {
            if (qualifiedCciValues[i] > qualifiedCciValues[i + 1] && qualifiedCciValues[i + 1] > qualifiedCciValues[i + 2] &&
            reversedLowPrices[index0] < reversedLowPrices[index1] && reversedLowPrices[index1] < reversedLowPrices[index2]) 
            {
                datetime klineTime0 = reversedKlineTimes[index0];
                datetime chinaTime0 = ConvertToChinaTime(klineTime0);
                datetime klineTime1 = reversedKlineTimes[index1];
                datetime chinaTime1 = ConvertToChinaTime(klineTime1);
                datetime klineTime2 = reversedKlineTimes[index2];
                datetime chinaTime2 = ConvertToChinaTime(klineTime2);

                Print("qualifiedCciValues[", i, "] 的CCI值: ", qualifiedCciValues[i], 
                "，开盘时间: ", TimeToString(klineTime0), "，中国时间: ", TimeToString(chinaTime0), 
                "，最低价: ", reversedLowPrices[index0], "，最高价: ", reversedHighPrices[index0]);
                Print("qualifiedCciValues[", i + 1, "] 的CCI值: ", qualifiedCciValues[i + 1], 
                "，开盘时间: ", TimeToString(klineTime1), "，中国时间: ", TimeToString(chinaTime1), 
                "，最低价: ", reversedLowPrices[index1], "，最高价: ", reversedHighPrices[index1]);
                Print("qualifiedCciValues[", i + 2, "] 的CCI值: ", qualifiedCciValues[i + 2], 
                "，开盘时间: ", TimeToString(klineTime2), "，中国时间: ", TimeToString(chinaTime2), 
                "，最低价: ", reversedLowPrices[index2], "，最高价: ", reversedHighPrices[index2]);

                // 创建直线对象连接两根K线
                string objectName = "Line_" + IntegerToString(i);
                ObjectCreate(0, objectName, OBJ_TREND, 0, reversedKlineTimes[index0], reversedLowPrices[index0], reversedKlineTimes[index2], reversedLowPrices[index2]);
                ObjectSetInteger(0, objectName, OBJPROP_COLOR, clrGreen); // 设置线段颜色为绿色
                ObjectSetInteger(0, objectName, OBJPROP_WIDTH, 3); // 设置线段宽度为3
                ObjectSetInteger(0, objectName, OBJPROP_STYLE, STYLE_SOLID); // 设置线段样式为实线
            }
        }
    }
}
// 判断并打印符合条件的相邻CCI值及其对应K线信息，并绘制蓝色线段
void CheckAndPrintAdjacentCCI(double &reversedCciValues[], datetime &reversedKlineTimes[], double &reversedLowPrices[], double &reversedHighPrices[]) {
    for (int i = 0; i < KLINE_NUMBER; i++) {
        if (reversedCciValues[i] > reversedCciValues[i + 1] && reversedLowPrices[i] < reversedLowPrices[i + 1]) {
            datetime chinaTime1 = ConvertToChinaTime(reversedKlineTimes[i]);
            datetime chinaTime2 = ConvertToChinaTime(reversedKlineTimes[i + 1]);
            Print("reversedCciValues[", i, "]：");
            Print("  开盘时间: ", TimeToString(reversedKlineTimes[i]), "，中国时间: ", TimeToString(chinaTime1));
            Print("  CCI值: ", reversedCciValues[i]);
            Print("  最低价: ", reversedLowPrices[i]);
            Print("  最高价: ", reversedHighPrices[i]);

            Print("reversedCciValues[", i + 1, "]：");
            Print("  开盘时间: ", TimeToString(reversedKlineTimes[i + 1]), "，中国时间: ", TimeToString(chinaTime2));
            Print("  CCI值: ", reversedCciValues[i + 1]);
            Print("  最低价: ", reversedLowPrices[i + 1]);
            Print("  最高价: ", reversedHighPrices[i + 1]);

            // 创建直线对象连接两根K线，颜色为蓝色
            string objectName = "AdjacentLine_" + IntegerToString(i);
            ObjectCreate(0, objectName, OBJ_TREND, 0, reversedKlineTimes[i], reversedLowPrices[i], reversedKlineTimes[i + 1], reversedLowPrices[i + 1]);
            ObjectSetInteger(0, objectName, OBJPROP_COLOR, clrBlue); // 设置线段颜色为蓝色
            ObjectSetInteger(0, objectName, OBJPROP_WIDTH, 3); // 设置线段宽度为3
            ObjectSetInteger(0, objectName, OBJPROP_STYLE, STYLE_SOLID); // 设置线段样式为实线
        }
    }
}

// 新增函数，判断并打印符合条件的CCI值及其对应K线信息
void CheckAndPrintPeakCCI(double &reversedCciValues[], datetime &reversedKlineTimes[], double &reversedHighPrices[]) {
    // 打印 reversedCciValues[0] 到 reversedCciValues[2] 的信息
    for (int i = 0; i < 3; i++) {
        datetime originalTime = reversedKlineTimes[i];
        datetime chinaTime = ConvertToChinaTime(originalTime);
        double cciValue = reversedCciValues[i];
        double highPrice = reversedHighPrices[i];
        Print("==========");
        Print("reversedCciValues[", i, "] 的欧美时间: ", TimeToString(originalTime));
        Print("reversedCciValues[", i, "] 的中国时间: ", TimeToString(chinaTime));
        Print("reversedCciValues[", i, "] 的CCI数值: ", cciValue);
        Print("reversedCciValues[", i, "] 这根K线的最高价: ", highPrice);
        Print("==========");
    }

    for (int i = 1; i < KLINE_NUMBER - 1; i++) {
        if (reversedCciValues[i] < reversedCciValues[i + 1] && reversedCciValues[i + 1] > reversedCciValues[i + 2]) {
            datetime originalTime = reversedKlineTimes[i + 1];
            datetime chinaTime = ConvertToChinaTime(originalTime);
            double cciValue = reversedCciValues[i + 1];
            double highPrice = reversedHighPrices[i + 1];

            Print("调试信息：满足 reversedCciValues[", i, "] < reversedCciValues[", i + 1, "] > reversedCciValues[", i + 2, "]");
            Print("reversedCciValues[", i + 1, "] 的欧美时间: ", TimeToString(originalTime));
            Print("reversedCciValues[", i + 1, "] 的中国时间: ", TimeToString(chinaTime));
            Print("reversedCciValues[", i + 1, "] 的CCI数值: ", cciValue);
            Print("reversedCciValues[", i + 1, "] 这根K线的最高价: ", highPrice);
        }
    }

    // 新增代码部分（修改后的动态数组）
    double peakCciValues[];
    int peakIndices[];
    int peakCount = 0;

    Print("函数开始时 peakCciValues 大小: ", ArraySize(peakCciValues)); // 输出 0
    ArrayResize(peakCciValues, KLINE_NUMBER);
    Print("分配后 peakCciValues 大小: ", ArraySize(peakCciValues)); // 输出 KLINE_NUMBER

    // 调整动态数组大小
    ArrayResize(peakCciValues, KLINE_NUMBER);
    ArrayResize(peakIndices, KLINE_NUMBER);

    Print("函数开始时 peakCciValues 大小: ", ArraySize(peakCciValues)); // 输出 0
    ArrayResize(peakCciValues, KLINE_NUMBER);
    Print("分配后 peakCciValues 大小: ", ArraySize(peakCciValues)); // 输出 KLINE_NUMBER


    // 再次遍历找出满足条件的中间值并存入数组
    for (int i = 1; i < KLINE_NUMBER - 1; i++) {
        if (reversedCciValues[i] < reversedCciValues[i + 1] && reversedCciValues[i + 1] > reversedCciValues[i + 2]) {
            peakCciValues[peakCount] = reversedCciValues[i + 1];
            peakIndices[peakCount] = i + 1; // 记录索引
            peakCount++;
        }
    }

    // 遍历存储中间值的数组并打印相关信息
    Print("以下是存储在新数组中的满足条件的CCI值信息：");
    for (int i = 0; i < peakCount; i++) {
        int index = peakIndices[i];
        datetime originalTime = reversedKlineTimes[index];
        datetime chinaTime = ConvertToChinaTime(originalTime);
        double cciValue = peakCciValues[i];
        double highPrice = reversedHighPrices[index];

        Print("peakCciValues[", i, "] 的欧美时间: ", TimeToString(originalTime));
        Print("peakCciValues[", i, "] 的中国时间: ", TimeToString(chinaTime));
        Print("peakCciValues[", i, "] 的CCI数值: ", cciValue);
        Print("peakCciValues[", i, "] 这根K线的最高价: ", highPrice);
    }

    // 比较相邻的 peakCciValues 元素并绘制线段
    for (int i = 0; i < peakCount - 1; i++) {
        if (peakCciValues[i] < peakCciValues[i + 1]) {
            int index1 = peakIndices[i];
            int index2 = peakIndices[i + 1];
            double highPrice1 = reversedHighPrices[index1];
            double highPrice2 = reversedHighPrices[index2];

            if (highPrice1 > highPrice2) {
                datetime originalTime1 = reversedKlineTimes[index1];
                datetime chinaTime1 = ConvertToChinaTime(originalTime1);
                double cciValue1 = peakCciValues[i];

                datetime originalTime2 = reversedKlineTimes[index2];
                datetime chinaTime2 = ConvertToChinaTime(originalTime2);
                double cciValue2 = peakCciValues[i + 1];

                Print("peakCciValues[", i, "] 与 peakCciValues[", i + 1, "] 满足条件：");
                Print("peakCciValues[", i, "] 的欧美时间: ", TimeToString(originalTime1));
                Print("peakCciValues[", i, "] 的中国时间: ", TimeToString(chinaTime1));
                Print("peakCciValues[", i, "] 的CCI数值: ", cciValue1);
                Print("peakCciValues[", i, "] 这根K线的最高价: ", highPrice1);

                Print("peakCciValues[", i + 1, "] 的欧美时间: ", TimeToString(originalTime2));
                Print("peakCciValues[", i + 1, "] 的中国时间: ", TimeToString(chinaTime2));
                Print("peakCciValues[", i + 1, "] 的CCI数值: ", cciValue2);
                Print("peakCciValues[", i + 1, "] 这根K线的最高价: ", highPrice2);

                // 创建直线对象连接两根K线的最高价，颜色为黄色
                string objectName = "PeakLine_" + IntegerToString(i);
                ObjectCreate(0, objectName, OBJ_TREND, 0, reversedKlineTimes[index1], highPrice1, reversedKlineTimes[index2], highPrice2);
                ObjectSetInteger(0, objectName, OBJPROP_COLOR, clrYellow); // 设置线段颜色为黄色
                ObjectSetInteger(0, objectName, OBJPROP_WIDTH, 3); // 设置线段宽度为3
                ObjectSetInteger(0, objectName, OBJPROP_STYLE, STYLE_SOLID); // 设置线段样式为实线
            }
        }
    }

    // 新增：从reversedCciValues[1]开始遍历比较
    for (int i = 1; i < KLINE_NUMBER; i++) {
        if (reversedCciValues[i] < reversedCciValues[i + 1]) {
            double highPrice1 = reversedHighPrices[i];
            double highPrice2 = reversedHighPrices[i + 1];

            if (highPrice1 > highPrice2) {
                datetime originalTime1 = reversedKlineTimes[i];
                datetime chinaTime1 = ConvertToChinaTime(originalTime1);
                double cciValue1 = reversedCciValues[i];

                datetime originalTime2 = reversedKlineTimes[i + 1];
                datetime chinaTime2 = ConvertToChinaTime(originalTime2);
                double cciValue2 = reversedCciValues[i + 1];

                Print("reversedCciValues[", i, "] 与 reversedCciValues[", i + 1, "] 满足条件：");
                Print("reversedCciValues[", i, "] 的欧美时间: ", TimeToString(originalTime1));
                Print("reversedCciValues[", i, "] 的中国时间: ", TimeToString(chinaTime1));
                Print("reversedCciValues[", i, "] 的CCI数值: ", cciValue1);
                Print("reversedCciValues[", i, "] 这根K线的最高价: ", highPrice1);

                Print("reversedCciValues[", i + 1, "] 的欧美时间: ", TimeToString(originalTime2));
                Print("reversedCciValues[", i + 1, "] 的中国时间: ", TimeToString(chinaTime2));
                Print("reversedCciValues[", i + 1, "] 的CCI数值: ", cciValue2);
                Print("reversedCciValues[", i + 1, "] 这根K线的最高价: ", highPrice2);

                // 创建直线对象连接两根K线的最高价，颜色为紫色
                string objectName = "ReversedLine_" + IntegerToString(i);
                ObjectCreate(0, objectName, OBJ_TREND, 0, reversedKlineTimes[i], highPrice1, reversedKlineTimes[i + 1], highPrice2);
                ObjectSetInteger(0, objectName, OBJPROP_COLOR, clrPurple); // 设置线段颜色为紫色
                ObjectSetInteger(0, objectName, OBJPROP_WIDTH, 3); // 设置线段宽度为3
                ObjectSetInteger(0, objectName, OBJPROP_STYLE, STYLE_SOLID); // 设置线段样式为实线
            }
        }
    }
    Print("函数开始时 peakCciValues 大小: ", ArraySize(peakCciValues)); // 输出 0
    ArrayResize(peakCciValues, KLINE_NUMBER);
    Print("分配后 peakCciValues 大小: ", ArraySize(peakCciValues)); // 输出 KLINE_NUMBER
}

// 脚本启动函数
void OnStart()
{
    // 根据 USE_FIXED_PERIOD 宏的值选择时间周期
    ENUM_TIMEFRAMES timeframe;
    if (USE_FIXED_PERIOD == 1) {
        timeframe = FIXED_TIMEFRAME_PERIOD;
    } else {
        timeframe = Period(); // 获取当前图表的周期
    }

    // 初始化CCI指标
    hCCI = iCCI(SYMBOL, timeframe, CCI_Period, PRICE_TYPICAL);

    if (hCCI == INVALID_HANDLE)
    {
        Print("无法初始化CCI指标，错误代码: ", GetLastError());
        return;
    }
    // 调整动态数组大小
    ArrayResize(cciValues, KLINE_NUMBER + 1, 0);
    ArrayResize(klineTimes, KLINE_NUMBER + 1, 0);
    ArrayResize(lowPrices, KLINE_NUMBER + 1, 0);
    ArrayResize(highPrices, KLINE_NUMBER + 1, 0);
    ArrayResize(reversedCciValues, KLINE_NUMBER + 1, 0);
    ArrayResize(reversedKlineTimes, KLINE_NUMBER + 1, 0);
    ArrayResize(reversedLowPrices, KLINE_NUMBER + 1, 0);
    ArrayResize(reversedHighPrices, KLINE_NUMBER + 1, 0);
    ArrayResize(qualifiedCciValues, KLINE_NUMBER, 0);

    if (CopyBuffer(hCCI, 0, 0, KLINE_NUMBER + 1, cciValues) < 0)
    {
        Print("无法从CCI指标缓冲区复制数据，错误代码: ", GetLastError());
        IndicatorRelease(hCCI);
        return;
    }
    if (CopyTime(SYMBOL, timeframe, 0, KLINE_NUMBER + 1, klineTimes) < 0)
    {
        Print("无法从K线获取时间数据，错误代码: ", GetLastError());
        IndicatorRelease(hCCI);
        return;
    }
    if (CopyLow(SYMBOL, timeframe, 0, KLINE_NUMBER + 1, lowPrices) < 0)  // 获取K线最低价
    {
        Print("无法从K线获取最低价数据，错误代码: ", GetLastError());
        IndicatorRelease(hCCI);
        return;
    }
    if (CopyHigh(SYMBOL, timeframe, 0, KLINE_NUMBER + 1, highPrices) < 0)  // 获取K线最高价
    {
        Print("无法从K线获取最高价数据，错误代码: ", GetLastError());
        IndicatorRelease(hCCI);
        return;
    }

    // 反转数组
    for (int i = 0; i <= KLINE_NUMBER; i++)
    {
        reversedCciValues[i] = cciValues[KLINE_NUMBER - i];
        reversedKlineTimes[i] = klineTimes[KLINE_NUMBER - i];
        reversedLowPrices[i] = lowPrices[KLINE_NUMBER - i];
        reversedHighPrices[i] = highPrices[KLINE_NUMBER - i];
    }

    datetime klineTimeduo;//存第3根时间，条件符合就开多单

    // 正常顺序遍历反转后的数组，输出CCI信息
    for (int i = 0; i <= KLINE_NUMBER; i++)
    {
        double cciValue = reversedCciValues[i];
        datetime klineTime = reversedKlineTimes[i];
        datetime chinaTime = ConvertToChinaTime(klineTime);
        if (cciValue != EMPTY_VALUE)
        {
            Print("第 ", i, " 根K线（时间: ", TimeToString(klineTime), "，中国时间: ", TimeToString(chinaTime), "）的CCI数值: ", cciValue);
        }
        else
        {
            Print("无法获取第 ", i, " 根K线的CCI数值，错误代码: ", GetLastError());
        }

        if(i==2)
        {
            klineTimeduo = reversedKlineTimes[i];
        }
    }

    int qualifiedCount = 0;

    // 从reversedCciValues[1]开始遍历，判断条件并输出相关信息
    for (int i = 1; i <= KLINE_NUMBER - 2; i++)
    {
        // 打印调试信息
        Print("调试信息：reversedCciValues[", i, "] = ", reversedCciValues[i], 
              ", reversedCciValues[", i + 1, "] = ", reversedCciValues[i + 1], 
              ", reversedCciValues[", i + 2, "] = ", reversedCciValues[i + 2]);

        if (reversedCciValues[i] > reversedCciValues[i + 1] && reversedCciValues[i + 1] < reversedCciValues[i + 2])
        {
            qualifiedCciValues[qualifiedCount] = reversedCciValues[i + 1];
            qualifiedCount++;

            datetime klineTime = reversedKlineTimes[i + 1];
            datetime chinaTime = ConvertToChinaTime(klineTime);
            Print("第 ", i + 1, " 根K线（时间: ", TimeToString(klineTime), "，中国时间: ", TimeToString(chinaTime), 
                  "）的CCI数值: ", reversedCciValues[i + 1], "，最低价: ", reversedLowPrices[i + 1], "，最高价: ", reversedHighPrices[i + 1]);
        }
    }

    // 打印符合条件的CCI值及其对应的K线开盘时间、最低价和最高价
    Print("符合条件的CCI值及其对应信息：");
    for (int i = 0; i < qualifiedCount; i++)
    {
        // 找出该CCI值对应的原始索引
        for (int j = 0; j <= KLINE_NUMBER; j++)
        {
            if (qualifiedCciValues[i] == reversedCciValues[j])
            {
                datetime klineTime = reversedKlineTimes[j];
                datetime chinaTime = ConvertToChinaTime(klineTime);
                Print("CCI值: ", qualifiedCciValues[i], "，开盘时间: ", TimeToString(klineTime), "，中国时间: ", TimeToString(chinaTime), "，最低价: ", reversedLowPrices[j], "，最高价: ", reversedHighPrices[j]);
                break;
            }
        }
    }

    // 对qualifiedCciValues数组进行遍历比较
    for (int i = 0; i < qualifiedCount - 1; i++)
    {
        int index1 = -1, index2 = -1;
        // 找出qualifiedCciValues[i]在reversedCciValues中的索引
        for (int j = 0; j <= KLINE_NUMBER; j++)
        {
            if (qualifiedCciValues[i] == reversedCciValues[j])
            {
                index1 = j;
                break;
            }
        }
        // 找出qualifiedCciValues[i + 1]在reversedCciValues中的索引
        for (int j = 0; j <= KLINE_NUMBER; j++)
        {
            if (qualifiedCciValues[i + 1] == reversedCciValues[j])
            {
                index2 = j;
                break;
            }
        }

        if (index1 != -1 && index2 != -1)
        {
            if (qualifiedCciValues[i] > qualifiedCciValues[i + 1] && reversedLowPrices[index1] < reversedLowPrices[index2])
            {
                datetime klineTime1 = reversedKlineTimes[index1];
                datetime chinaTime1 = ConvertToChinaTime(klineTime1);
                datetime klineTime2 = reversedKlineTimes[index2];
                datetime chinaTime2 = ConvertToChinaTime(klineTime2);
                Print("qualifiedCciValues[", i, "] 的CCI值: ", qualifiedCciValues[i], 
                      "，开盘时间: ", TimeToString(klineTime1), "，中国时间: ", TimeToString(chinaTime1), 
                      "，最低价: ", reversedLowPrices[index1], "，最高价: ", reversedHighPrices[index1]);
                Print("qualifiedCciValues[", i + 1, "] 的CCI值: ", qualifiedCciValues[i + 1], 
                      "，开盘时间: ", TimeToString(klineTime2), "，中国时间: ", TimeToString(chinaTime2), 
                      "，最低价: ", reversedLowPrices[index2], "，最高价: ", reversedHighPrices[index2]);

                // 创建直线对象连接两根K线
                string objectName = "Line_" + IntegerToString(i);
                ObjectCreate(0, objectName, OBJ_TREND, 0, reversedKlineTimes[index1], reversedLowPrices[index1], reversedKlineTimes[index2], reversedLowPrices[index2]);
                ObjectSetInteger(0, objectName, OBJPROP_COLOR, clrRed); // 设置线段颜色为红色
                ObjectSetInteger(0, objectName, OBJPROP_WIDTH, 3); // 设置线段宽度为3
                ObjectSetInteger(0, objectName, OBJPROP_STYLE, STYLE_SOLID); // 设置线段样式为实线

                if (klineTimeduo == klineTime1) 
                {
                    Print("OK开单");//符合开多单
                }
            }

        }
    }

    // 调用新函数进行相邻CCI值判断和信息打印
    CheckAndPrintAdjacentCCI(reversedCciValues, reversedKlineTimes, reversedLowPrices, reversedHighPrices);

    // 调用新增函数判断并打印符合条件的CCI值及其对应K线信息
    CheckAndPrintPeakCCI(reversedCciValues, reversedKlineTimes, reversedHighPrices);
    // 调用比较函数并传入所有必要参数
    CompareThreeElements(qualifiedCciValues, qualifiedCount, reversedLowPrices, reversedHighPrices, reversedKlineTimes, reversedCciValues);
    // 释放指标处理器
    IndicatorRelease(hCCI);
}